/** 
 * Functions regarding the scheduler
 */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include "scheduler.h"


schedule_list *schedule_table[10];


/**
 * Removes the next event from the schedule for processing
 */
event * next_event(schedule *s)
{
  event *next = s->head;
  s->head =  next->next;
  return next;
}

int has_event(schedule *s)
{
  return (s->head != NULL) ? 1 : 0;
}

/**
 * Add an event to a schedule
 */
schedule * join_schedules(schedule *a,  schedule *b)
{
  schedule *c = malloc(sizeof(schedule));
	if (c==NULL){
	exit(1);
}	
  //Put the event at the head of the schedule
  c->head = a->head;
  event *tmp;
  for(tmp = c->head; tmp->next != NULL; tmp = tmp->next);
  tmp->next = b->head;
  free(a);
  free(b);
  bubble_sort(c);
  return c;
}

/**
 * Sorts a schedule via Bubble Sort
 */
void bubble_sort(schedule *s)
{	
  int swapped;
  do
    {
      event *dummy = NULL;
      event **curr = &s->head;
      event **prev = &dummy;
      swapped = 0;
		
      while(*curr != NULL)
	{
	  event *a = *prev;
	  event *b = *curr;
	  event *c = NULL;

	  if(*prev == NULL )
	    {
				
	    }
	  else if(a->timestamp > b->timestamp)
	    {
	      swap(s,*prev,*curr);
	      swapped = 1;
	      //Stop if we reach the end of the list
	      if(*curr == NULL)
		{
		  break;
		}			
	    }
	  prev = curr;
	  c = *curr;
	  curr = &c->next;
	}
    }while(swapped);
  return;
}

/**
 * Turn a number of events into a schedule
 */
schedule * make_schedule(int cnt, ...)
{
  va_list events;
  int i, sum;
  schedule *s = malloc(sizeof(schedule));
  if(s == NULL) {
	exit(1);
}  
  event *tmp;

  //Initialize
  va_start(events, cnt);
     
  for (i = 0; i < cnt; i++) 
    {
      event *e = va_arg(events, event *);
      //Start at the head
      if(i == 0)
	{
	  s->head = e;
	  
	}
      else 
	{
	  tmp->next = e;
	  //End of list
	  if(i == (cnt - 1))
	    {
	      e->next = NULL;
	    }
	}
      tmp = e;
    }
  va_end (events);             
  return s;
}

/**
 * Swaps two adjacent elements in the schedule
 */
void swap(schedule *s, event *a, event *b)
{
  event *prev = NULL;
  event *t2 = NULL;
  prev = s->head;
  t2 = b->next;
	
  if(prev == a)
    {
      s->head = b;		
      b->next = a;
      a->next = t2;
    }
  else
    {
      while(prev->next != a)
	{
	  prev = prev->next;
	}

      prev->next = b;
		
      b->next = a;
      a->next = t2;
    }
  return;
}
